<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0" xmlns:sql="http://xml.apache.org/xalan/sql"
  xmlns:java="http://xml.apache.org/xalan/java"
  xmlns:exslt="http://exslt.org/common"
  extension-element-prefixes="java sql exslt">
  <xsl:output indent="yes"/>
  <xsl:param name="user">user</xsl:param>
  <xsl:param name="password">password</xsl:param>
  <xsl:variable name="tdb"
    select="sql:new('com.mysql.jdbc.Driver',
    concat('jdbc:mysql://localhost:3306/templatedb?user=',$user,'&amp;password=',$password))"/>
  <xsl:variable name="tquery"> SELECT t.ID, t.OID, t.isOpen, t.title,
    y.templatetype type, t.description, t.keywords, c.context,
    t.impliedTemplate implied, t.notes from template t LEFT JOIN
    dictionarycontext c on t.primaryContext = c.ID LEFT JOIN
    template_type y on y.id = t.templateType ORDER BY t.ID </xsl:variable>
  <xsl:variable name="cquery"> SELECT c.ID, c.parentConstraintID,
    c.templateID, c.order, c.isBranch, ct1.conftype businessConformance,
    c.cardinality, ctx.context, t.OID containedTemplate, c.isPrimitive,
    c.constraintNarrative narrative, ct2.conftype valueConformance,
    v.bindingType staticDynamic, vs.OID valueSetOID, c.version,
    c.codeOrValue, c.codeSystemOID, c.displayName, c.datatype,
    c.schematronTest FROM template_constraint c LEFT JOIN
    conformance_type ct1 ON ct1.id = c.businessConformance LEFT JOIN
    conformance_type ct2 ON ct2.id = c.valueConformance LEFT JOIN
    dictionarycontext ctx ON c.context = ctx.ID LEFT JOIN
    vocbinding_type v ON c.staticDynamic = v.id LEFT JOIN template t ON
    c.containedTemplate = t.ID LEFT JOIN valueset vs ON c.valueSetOID =
    vs.ID ORDER BY c.ID </xsl:variable>
  <xsl:variable name="csquery"> SELECT ID, OID, codeSystemName,
    description FROM dictionarycodesystem ORDER BY
    codeSystemName</xsl:variable>
  <xsl:variable name="vsquery"> SELECT ID, OID, valueSetName,
    valueSetCode, intensional, description, intensionalDefinition FROM
    valueset ORDER BY valueSetName</xsl:variable>
  <xsl:variable name="vmquery"> SELECT ID, valueSetOId, code,
    codeSystemOID, displayName FROM valuesetmember </xsl:variable>
  <xsl:template match="/">
    <xsl:call-template name="organize">
      <xsl:with-param name="data">
        <tdb>
          <templates>
            <xsl:call-template name="SQLtoXML">
              <xsl:with-param name="resultXML">
                <xsl:copy-of select="sql:query($tdb, $tquery)"/>
              </xsl:with-param>
              <xsl:with-param name="map">aaaeaeeaae</xsl:with-param>
            </xsl:call-template>
          </templates>
          <constraints>
            <xsl:call-template name="SQLtoXML">
              <xsl:with-param name="resultXML">
                <xsl:copy-of select="sql:query($tdb, $cquery)"/>
              </xsl:with-param>
              <xsl:with-param name="map"
                >aaaaaaaaaaeaaaaaaaae</xsl:with-param>
              <xsl:with-param name="name">constraint</xsl:with-param>
            </xsl:call-template>
          </constraints>
          <codeSystems>
            <xsl:call-template name="SQLtoXML">
              <xsl:with-param name="resultXML">
                <xsl:copy-of select="sql:query($tdb, $csquery)"/>
              </xsl:with-param>
              <xsl:with-param name="map">aaae</xsl:with-param>
              <xsl:with-param name="name">codeSystem</xsl:with-param>
            </xsl:call-template>
          </codeSystems>
          <valueSets>
            <xsl:call-template name="SQLtoXML">
              <xsl:with-param name="resultXML">
                <xsl:copy-of select="sql:query($tdb, $vsquery)"/>
              </xsl:with-param>
              <xsl:with-param name="map">aaaaaae</xsl:with-param>
              <xsl:with-param name="name">valueSet</xsl:with-param>
            </xsl:call-template>
          </valueSets>
          <members>
            <xsl:call-template name="SQLtoXML">
              <xsl:with-param name="resultXML">
                <xsl:copy-of select="sql:query($tdb, $vmquery)"/>
              </xsl:with-param>
              <xsl:with-param name="map">aaaaa</xsl:with-param>
              <xsl:with-param name="name">member</xsl:with-param>
            </xsl:call-template>
          </members>
        </tdb>
      </xsl:with-param>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="organize">
    <xsl:param name="data"/>
    <xsl:variable name="d" select="exslt:node-set($data)"/>
    <tdb
      title="{sql:query($tdb, &quot;SELECT title FROM implementationguide&quot;)//col[1]}">
      <templates>
        <xsl:apply-templates select="$d/tdb/templates/template">
          <xsl:sort
            select="translate(substring(@type,5,1),&quot;miynf&quot;,&quot;12345&quot;)"/>
          <xsl:sort select="title"/>
        </xsl:apply-templates>
      </templates>
      <xsl:copy-of select="$d/tdb/codeSystems"/>
      <valueSets>
        <xsl:apply-templates select="$d/tdb/valueSets/valueSet"/>
      </valueSets>
    </tdb>
  </xsl:template>

  <xsl:template match="template">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="@context"/>
      <xsl:copy-of select="*"/>
      <xsl:apply-templates
        select="/tdb/constraints/constraint[@templateID = current()/@ID and 
        not(@parentConstraintID)]">
        <xsl:sort select="@order" data-type="number"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="constraint">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:if test="@datatype">
        <xsl:attribute name="datatype">
          <xsl:value-of select="translate(@datatype,'&lt;&gt;','_')"/>
        </xsl:attribute>
      </xsl:if>
      <xsl:if test="@cardinality">
        <xsl:attribute name="lower"><xsl:value-of select="substring(@cardinality,1,1)"/></xsl:attribute>
        <xsl:attribute name="upper"><xsl:value-of select="substring(@cardinality,4,1)"/></xsl:attribute>
      </xsl:if>
      <xsl:apply-templates select="@context"/>
      <xsl:copy-of select="*"/>
      <xsl:apply-templates
        select="/tdb/constraints/constraint[@parentConstraintID = current()/@ID]">
        <xsl:sort select="@order" data-type="number"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="valueSet">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:copy-of select="*"/>
      <xsl:apply-templates
        select="/tdb/members/member[@valueSetOId = current()/@OID]">
        <xsl:sort select="@displayName"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="member">
    <xsl:copy-of select="."/>
  </xsl:template>
  
  <xsl:template match="@context">
    <xsl:attribute name="context">
      <xsl:call-template name="context"/>
    </xsl:attribute>
  </xsl:template>
  
  <xsl:template name="context">
    <xsl:param name="ctx" select="."/>
    <xsl:variable name='left' select="substring-before($ctx,'/')"/>  
    <xsl:variable name='right' select="substring-after($ctx,'/')"/>
    <xsl:choose>
      <xsl:when test='$left = ""'>
        <xsl:call-template name="qname">
          <xsl:with-param name="name" select="$ctx"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="qname">
          <xsl:with-param name="name" select="$left"/>
        </xsl:call-template>
        <xsl:text>/</xsl:text>
        <xsl:call-template name='context'>
          <xsl:with-param name="ctx" select="$right"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>    
  </xsl:template>
  
  <xsl:template name='qname'>
    <xsl:param name="name"/>
    <xsl:choose>
      <xsl:when test="contains($name,':')"><xsl:value-of select="$name"/></xsl:when>
      <xsl:when test="contains($name,'@')"><xsl:value-of select="$name"/></xsl:when>
      <xsl:otherwise>cda:<xsl:value-of select="$name"/></xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  
  <xsl:template match="text()"/>

  <xsl:template name="SQLtoXML">
    <xsl:param name="resultXML" select="."/>
    <xsl:param name="result" select="exslt:node-set($resultXML)"/>
    <xsl:param name="map"/>
    <xsl:param name="meta" select="$result/sql/metadata"/>
    <xsl:param name="name" select="$meta/column-header[1]/@table-name"/>

    <xsl:for-each select="$result/sql/row-set/row">
      <xsl:element name="{$name}">
        <xsl:for-each select="col">
          <xsl:variable name="pos" select="position()"/>
          <xsl:if
            test="substring($map, $pos, 1) = &quot;a&quot; and string(.) != &quot;&quot;">
            <xsl:attribute name="{@column-label}">
              <xsl:value-of select="."/>
            </xsl:attribute>
          </xsl:if>
        </xsl:for-each>
        <xsl:for-each select="col">
          <xsl:variable name="pos" select="position()"/>
          <xsl:if
            test="substring($map, $pos, 1) != &quot;a&quot; and string(.) != &quot;&quot;">
            <xsl:element name="{@column-label}">
              <xsl:value-of select="."/>
            </xsl:element>
          </xsl:if>
        </xsl:for-each>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
